package site.lizhivscaomei.aliyun.oss.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import site.lizhivscaomei.aliyun.oss.config.OSSConfigProperties;
import site.lizhivscaomei.aliyun.oss.entity.CallbackRequest;
import site.lizhivscaomei.aliyun.oss.service.ClientDirectUploadService;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 默认阿里云OSS，客户端直传逻辑
 * Created by lizhi on 2019/1/10.
 */
public class DefaultClientDirectUploadServiceImpl implements ClientDirectUploadService {
    OSSConfigProperties ossConfigProperties;
    OSSClient ossClient;

    public DefaultClientDirectUploadServiceImpl(OSSConfigProperties ossConfigProperties, OSSClient ossClient) {
        this.ossClient = ossClient;
        this.ossConfigProperties = ossConfigProperties;
    }

    public Map getPolicyWithOutCallback() {
        long expireEndTime = System.currentTimeMillis() + ossConfigProperties.getExpire() * 1000;
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, ossConfigProperties.getDir());

        String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
        String encodedPolicy = null;
        try {
            byte[] binaryData = postPolicy.getBytes("utf-8");
            encodedPolicy = BinaryUtil.toBase64String(binaryData);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String postSignature = ossClient.calculatePostSignature(postPolicy);
        Map<String, String> respMap = new LinkedHashMap<String, String>();
        respMap.put("accessid", this.ossConfigProperties.getAccessId());
        respMap.put("policy", encodedPolicy);
        respMap.put("signature", postSignature);
        respMap.put("dir", ossConfigProperties.getDir());
        respMap.put("host", ossConfigProperties.getHost());
        respMap.put("expire", String.valueOf(expireEndTime / 1000));
        return respMap;
    }

    public Map getPolicyWithCallback() {
        Map respMap = this.getPolicyWithOutCallback();
        CallbackRequest callbackRequest = new CallbackRequest();
        callbackRequest.setCallbackUrl(this.ossConfigProperties.getCallbackUrl());
        callbackRequest.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
        callbackRequest.setCallbackBodyType("application/x-www-form-urlencoded");
        String base64CallbackBody = BinaryUtil.toBase64String(JSON.toJSONString(callbackRequest).getBytes());
        respMap.put("callback", base64CallbackBody);
        return respMap;
    }

    public AssumeRoleResponse getSTSAssumeRole() {
        try {
            // 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", ossConfigProperties.getAccessId(), ossConfigProperties.getAccessKey());
            DefaultAcsClient client = new DefaultAcsClient(profile);
            // 创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            if (StringUtils.isNotEmpty(ossConfigProperties.getStsApiVersion())) {
                request.setVersion(ossConfigProperties.getStsApiVersion());
            }
            request.setMethod(MethodType.POST);
            request.setProtocol(ProtocolType.HTTPS);
            request.setRoleArn(ossConfigProperties.getRoleArn());
            request.setRoleSessionName(ossConfigProperties.getRoleSessionName());
            request.setPolicy(ossConfigProperties.getStsPolicy());
            request.setDurationSeconds(ossConfigProperties.getStsDurationSeconds());
            // 发起请求，并得到response
            final AssumeRoleResponse response = client.getAcsResponse(request);
            return response;
        } catch (ClientException e) {
            throw e;
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (com.aliyuncs.exceptions.ClientException e) {
            e.printStackTrace();
        }
        return null;
    }

}
